package com.example.lbs.controller;

import com.example.lbs.dto.ShopDTO;
import com.example.lbs.model.Shop;
import com.example.lbs.service.ShopCacheService;
import com.example.lbs.service.ShopGeoService;
import com.example.lbs.service.ShopGeoService.NearbyShop;
import com.example.lbs.service.ShopService;
import org.springframework.web.bind.annotation.*;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/shops")
public class ShopController {
    private final ShopService shopService;
    private final ShopGeoService geoService;
    private final ShopCacheService cacheService;

    public ShopController(ShopService shopService, ShopGeoService geoService, ShopCacheService cacheService) {
        this.shopService = shopService;
        this.geoService = geoService;
        this.cacheService = cacheService;
    }

    @GetMapping
    public List<Shop> list(@RequestParam(required = false) String brand) {
        List<Shop> all = shopService.listAll();
        if (brand == null || brand.isBlank()) return all;
        String b = brand.toLowerCase();
        return all.stream().filter(s -> s.getBrand() != null && s.getBrand().toLowerCase().equals(b)).toList();
    }

    @PostMapping
    public Shop create(@RequestBody Shop shop) {
        // 统一交由服务层在事务提交后处理 GEO 与缓存
        return shopService.create(shop);
    }

    @PutMapping("/{id}")
    public Shop update(@PathVariable Long id, @RequestBody Shop shop) {
        shop.setId(id);
        // 统一交由服务层在事务提交后处理 GEO 与缓存
        return shopService.update(shop);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id, @RequestParam(required = false) String brand) {
        // 服务层会在事务提交后根据旧数据移除 GEO，并清理缓存
        shopService.delete(id);
    }

    @GetMapping("/{id}")
    public Shop get(@PathVariable Long id) {
        return cacheService.getShopDetail(id).orElseGet(() -> shopService.findById(id));
    }

    @GetMapping("/nearby")
    public List<ShopDTO> nearby(@RequestParam double lat,
                                @RequestParam double lng,
                                @RequestParam(defaultValue = "3000") double radius,
                                @RequestParam(defaultValue = "20") int limit,
                                @RequestParam(required = false) String brand) {
        List<NearbyShop> near = geoService.searchNearby(lng, lat, radius, limit, brand);
        return near.stream().map(n -> {
            Shop s = cacheService.getShopDetail(n.getShopId())
                    .orElseGet(() -> shopService.findById(n.getShopId()));
            return ShopDTO.from(s, n.getDistanceMeters());
        }).toList();
    }

    @GetMapping("/{id}/nav-url")
    public Map<String, String> navUrl(@PathVariable Long id) {
        Shop s = cacheService.getShopDetail(id).orElseGet(() -> shopService.findById(id));
        String name = URLEncoder.encode(s.getName(), StandardCharsets.UTF_8);
        String amap = String.format("https://uri.amap.com/navigation?to=%f,%f,%s&mode=car&policy=1",
                s.getLng(), s.getLat(), name);
        return Map.of("amap", amap);
    }
}